#pragma once
#include <mutex>
#include <condition_variable>
#include "channel.hpp"

namespace Muduo
{
    //将EventLoop和Thread整合到一起
    //创建线程->线程中实例化对象
    class LoopThread
    {
    public:
        //创建线程,设定线程入口函数
        LoopThread():_loop(nullptr),_thread(std::thread(&LoopThread::ThreadEntry,this))
        { }

        //返回当前线程关联的EventLoop对象指针
        EventLoop * GetLoop()
        {
            EventLoop * loop = nullptr;
            {
                std::unique_lock<std::mutex> lock(_mutex);//加锁
                _cond.wait(lock,[&](){return _loop != nullptr;});//loop为nullptr就一直阻塞
                loop = _loop;
            }
            return loop;
        }

    private:
        //实例化EventLoop对象,唤醒_cond上有可能阻塞的线程,并且开始运行EventLoop模块的功能
        void ThreadEntry()
        {
            //让生命周期随着LoopThread管理
            EventLoop loop;
            {
                std::unique_lock<std::mutex> lock(_mutex);//加锁
                _loop = &loop;
                _cond.notify_all();//唤醒_cond上有可能阻塞的线程
            }
            loop.Start();
        }

    private:
        //用于实现_loop获取的同步关系,避免线程创建了,但是_loop还没有实例化之前去获取_loop
        std::mutex _mutex;//互斥锁
        std::condition_variable _cond;//条件变量
        EventLoop * _loop;//EventLoop指针变量,这个对象需要在线程内实例化
        std::thread _thread;//EventLoop对应的线程
    };

    //针对LoopThread设计一个线程池
    class LoopThreadPool
    {
    public:
        LoopThreadPool(EventLoop * baseloop):_thread_count(0),_next_idx(0),_baseloop(baseloop){}

        //设置线程数量
        void SetThreadCount(int count)
        {
            _thread_count = count;
        }

        //创建所有的从属线程
        void Create()
        {
            if(_thread_count>0)
            {
                _threads.resize(_thread_count);
                _loops.resize(_thread_count);
                for(int i = 0;i<_thread_count;i++)
                {
                    _threads[i] = new LoopThread();
                    _loops[i] = _threads[i]->GetLoop();
                }
            }
        }

        //获取下个从属线程
        EventLoop * NextLoop()
        {
            if(_thread_count == 0)
            {
                return _baseloop;
            }
            _next_idx = (_next_idx+1)%_thread_count;
            return _loops[_next_idx];
        }
        
    private:
        int _thread_count;//线程数量,可为0
        int _next_idx;//负载均衡选择LoopThread->RR轮转
        EventLoop * _baseloop;//主Reactor的EventLoop,用于LoopThread从属线程为0情况使用
        std::vector<LoopThread*> _threads;//保存所有的LoopThread对象
        std::vector<EventLoop*> _loops;//保存所有的EventLoop对象
    };
}